package thread;

import cn.hutool.core.thread.ThreadFactoryBuilder;

import java.util.Queue;
import java.util.concurrent.*;

/**
 * @author : gscsd
 * @description: 1. 使用线程池可以有效控制线程数量，避免频繁创建和销毁线程的开销，提高系统性能和资源利用率
 * @date : 2025/9/27 14:23
 */
public class ThreadToolExecutorCreateThread {

    // 线程池的 7 个参数
    /**
     * 核心线程数, 不会销毁
     */
    public static final int corePoolSize = 5;
    /**
     * 最大线程数, 当核心线程数不够时, 会创建临时线程, 临时线程数超过最大线程数, 就会拒绝
     */
    public static final int maximumPoolSize = 10;
    /**
     * 临时线程数存活时间 , 临时线程数超过最大线程数, 超过存活时间就会销毁
     * 单位 下一个参数自定义
     * maximumPoolSize - corePoolSize = 临时线程数
     */
    public static final long keepAliveTime = 1;
    /**
     * 临时线程数存活时间单位
     */
    public static final TimeUnit unit = TimeUnit.SECONDS;
    /**
     * 临时线程数队列, 临时线程数超过最大线程数, 临时线程数队列就会满
     * 临时线程数队列满时, 拒绝策略
     *  一共有 7 种队列可用
     *  1. ArrayBlockingQueue: 有界, 数组队列, 先进先出, 顺序
     *  2. LinkedBlockingQueue: 有界, 链表队列, 先进先出, 默认容量 Integer.MAX_VALUE
     *  3. PriorityBlockingQueue: 无界, 链表队列, 优先级队列
     *  4. SynchronousQueue: 无界, 同步队列, 不存储元素, 每次插入操作必须等待另一个线程的对应移除操作
     *  5. DelayedQueue: 无界, 链表队列, 延迟队列, 延迟队列中的元素只有当延迟期满时才能从队列中获取
     *  6. LinkedTransferQueue: 无界, 链表队列, 链表队列, 链表队列的容量没有限制, 链表队列的插入和移除操作都是 O(1)
     *  7. LinkedBlockingDeque: 无界, 链表队列, 链表队列, 支持两端 插入和移除元素
     */
    public static final BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>(10);
    /**
     * 线程工厂, 创建线程
     */
    public static final ThreadFactory threadFactory = Executors.defaultThreadFactory();
    /**
     * 自定义工厂
     * */
    public static final ThreadFactory myThreadFactory = new ThreadFactoryBuilder()
            .setNamePrefix("my-thread-")  // %d 的作用是什么
            .setDaemon(false)
            .setPriority(Thread.MAX_PRIORITY)
            .setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
                @Override
                public void uncaughtException(Thread t, Throwable e) {
                    System.out.println("线程" + t.getName() + "出现异常");
                }
            })
            .build();

    /**
     * 临时线程数队列满时, 拒绝策略
     * 一共有 4 种拒绝策略
     * * 1. AbortPolicy: 默认策略, 抛出 RejectedExecutionException 异常
     * * 2. CallerRunsPolicy: 调用者运行策略, 由调用线程直接执行任务
     * * 3. DiscardOldestPolicy: 丢弃最老策略 丢弃队列种最老的任务
     * * 4. DiscardPolicy: 丢弃策略 直接丢弃, 不抛出异常
     */
    public static final ThreadPoolExecutor.DiscardPolicy discardPolicy = new ThreadPoolExecutor.DiscardPolicy();

    // 创建一个线程池
    public static ThreadPoolExecutor myThreadPool
            = new ThreadPoolExecutor(
            corePoolSize
            , maximumPoolSize
            , keepAliveTime
            , unit
            , workQueue
            // , threadFactory
            , myThreadFactory
            , discardPolicy
    );


    public void DefaultCreateThreadTool() {
        /**
         * 创建固定大小的线程池
         * */
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(5);
        /**
         * 创建一个缓存线程池
         * */
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        /**
         * 创建一个单线程的线程池
         * */
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        /**
         * 创建一个定长线程池, 支持定时及周期性任务执行
         * */
        ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);


    }

    public static void main(String[] args) {
        // 使用线程池 创建不需要返回的任务
        // for (int i = 0; i < 10; i++) {
        //     myThreadPool.execute(new Runnable() {
        //         @Override
        //         public void run() {
        //             System.out.println(Thread.currentThread().getName() + ">>>>" + "线程启动了");
        //         }
        //     });
        // }
        // myThreadPool.shutdown();

        // 使用线程池 创建需要返回的任务
        for (int i = 0; i < 10; i++) {
            Future<Integer> submit = myThreadPool.submit(new Callable<Integer>() {
                @Override
                public Integer call() throws Exception {
                    System.out.println(Thread.currentThread().getName() + ">>>>" + "线程启动了");
                    return 1;
                }
            });
            try {
                Integer integer = submit.get();
                System.out.println(integer);
            } catch (InterruptedException | ExecutionException e) {
                throw new RuntimeException(e);
            }
        }

        myThreadPool.shutdown();



    }


}


